package agenteAprend;

import racaa.MecAprendQ;
import simulador.Simulador;
import agente.Agente;
import ambiente.Accao;
import ambiente.Coordenada;
import ambiente.ElemAgente;


public class AgenteAprend extends Agente{
	
	private final double REF_MAX = 100;
	private final double GAMA = 0.99;
	private final double ALFA = 0.1;
	private final double EPSILON = 0.1;
	
	private MecAprendQ<Coordenada, Accao> mecAprd;
	private Coordenada estado;
	private Accao accao;
	private ElemAgente perPropria;
	
	private int passos = 0;
	private int passosCiclo = 0;
	private int ciclos = 1;

	
	private Coordenada gerarEstado(ElemAgente percepcao){
		return percepcao.getPosicao();
	}
	
	private double gerarReforco(ElemAgente percepcao, Coordenada estado, Coordenada estadoNovo){
		//Motivador atractor : carga
		if(percepcao.isCarga())
			return REF_MAX;
		//Motivador repulsor : colisao
		else if(percepcao.isColisao())
			return -REF_MAX;
		//Motivador repulsor : custo do movimento
		else
			return -estado.dist(estadoNovo);
	}
	
	@Override
	public void iniciar() {
		// TODO Auto-generated method stub
		Accao[] accoes = Accao.gerarAccoes(Accao.Tipo.PEGAR);
		estado = null;
		accao = null;
		mecAprd = new MecAprendQ<Coordenada, Accao>(accoes, ALFA, EPSILON, GAMA);
		
	}

	@Override
	public void percepcionar() {
		// TODO Auto-generated method stub
		perPropria = getSensorProprio().detectar();
		
	}

	@Override
	public void processar() {
		// TODO Auto-generated method stub
		Coordenada estadoNovo = gerarEstado(perPropria);
		if(accao!=null){
			double reforco = gerarReforco(perPropria,estado,estadoNovo);
			mecAprd.assimilar(estado, accao, estadoNovo, reforco);
		}
		estado = estadoNovo;
		accao = mecAprd.selAccao(estado);
		//Mostrar memoria
		Simulador.getVisInt(1).mostrarDireccao(accao.getDireccao(), estado.getX(), estado.getY());
		Simulador.getVisInt(1).marcar(100, mecAprd.getMaxQ(estado), 0.5, true, estado.getX(),estado.getY());
	}
	
	@Override
	public void agir() {
		// TODO Auto-generated method stub
		//Se agente atingiu objectivo, reenicia
		if(perPropria.isCarga()){
			accao=null;
			//Reeniciar ambiente
			this.getAmb().reIniciar();
			//Actualizar contadores
			ciclos++;
			passosCiclo = 0;
			//Reeniciar representacao grafica d memoria
			Simulador.getVisInt(1).limpar();
			
		//Se nao, continua a agir...	
		}else{
			this.getActuador().actuar(accao);
			passos++;
			passosCiclo++;
		}
		Simulador.mostrarTexto("Ciclo: "+ciclos+"\tPassos Ciclo: "+passosCiclo+"\tPassos: "+passos);
	}
	

}
